Skip to content

feat: add SWR local storage cache layer for offline dashboard resiliency (#2801) - #3348

Open
yachikadev wants to merge 8 commits into
Priyanshu-byte-coder:mainfrom
yachikadev:feat/swr-dashboard-cache
Open

feat: add SWR local storage cache layer for offline dashboard resiliency (#2801)#3348
yachikadev wants to merge 8 commits into
Priyanshu-byte-coder:mainfrom
yachikadev:feat/swr-dashboard-cache

Conversation

@yachikadev

Copy link
Copy Markdown
Contributor

Summary

Implements a Stale-While-Revalidate (SWR) local storage cache layer for the dashboard's Streak Tracker and Goal Tracker widgets, so users see their last-known data instantly on load instead of a blank/loading state — even on spotty networks, during GitHub API rate-limiting, or fully offline.

Closes #2801

Changes

  • src/lib/localCache.ts (new) — lightweight saveSnapshot / getSnapshot / clearSnapshot helpers backed by localStorage, with try/catch guards so a full, disabled, or missing localStorage never throws at runtime.
  • src/components/StreakTracker.tsx — on mount, hydrates instantly from the last cached streak/contribution snapshot before the network call resolves. On successful fetch, persists the new snapshot. On fetch failure, falls back to the cached snapshot instead of showing an error.
  • src/components/GoalTracker.tsx — same pattern applied to the goals list: instant hydration from cache, snapshot saved on successful load, cached goals shown if the live fetch fails.

How it works

  1. Instant hydration — a useEffect on mount reads the cached snapshot from localStorage and populates state immediately, skipping the loading spinner if data is available.
  2. Background sync — the existing fetch logic runs unchanged in parallel; on success it silently overwrites both the UI state and the cached snapshot.
  3. Graceful fallback — if the live request fails (offline, rate-limited, etc.), the cached snapshot is shown instead of an error message, whenever one exists.

Notes

  • Scoped to the two widgets driven by /api/metrics and /api/goals (streaks + goals), matching the issue's acceptance criteria. Other widgets are untouched and can adopt the same localCache.ts utility in future PRs if desired.

Adds saveSnapshot/getSnapshot/clearSnapshot helpers with
try-catch guards so localStorage failures (disabled, quota
full, SSR context) never throw at runtime.
Adds saveSnapshot/getSnapshot/clearSnapshot helpers with
try-catch guards so localStorage failures (disabled, quota
full, SSR context) never throw at runtime.
- Load last cached streak/contribution data from localStorage
  on mount before the network request resolves
- Persist fresh data to localStorage on successful fetch
- Fall back to cached snapshot instead of showing an error
  when the live fetch fails (offline / rate-limited)

Part of Priyanshu-byte-coder#2801
@github-actions github-actions Bot added gssoc26 GSSoC 2026 contribution type:feature GSSoC type bonus: new feature labels Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

GSSoC Label Checklist 🏷️

@Priyanshu-byte-coder — please apply the appropriate labels before merging:

Difficulty (pick one):

  • level:beginner — 20 pts
  • level:intermediate — 35 pts
  • level:advanced — 55 pts
  • level:critical — 80 pts

Quality (optional):

  • quality:clean — ×1.2 multiplier
  • quality:exceptional — ×1.5 multiplier

Validation (required to score):

  • gssoc:approved — counts for points
  • gssoc:invalid / gssoc:spam / gssoc:ai-slop — does not score

Type labels (type:*) are auto-detected from files and title. Review and adjust if needed.
Points formula: (difficulty × quality_multiplier) + type_bonus

@github-actions github-actions Bot added type:bug GSSoC type bonus: bug fix type:design GSSoC type bonus: UI/design (+10 pts) type:performance GSSoC type bonus: performance (+15 pts) labels Aug 2, 2026
- Load last cached goals list from localStorage on mount
- Persist fresh goals to localStorage on successful load
- Fall back to cached goals instead of an error message
  when the live fetch fails

Closes Priyanshu-byte-coder#2801
@yachikadev
yachikadev force-pushed the feat/swr-dashboard-cache branch from 7675cab to 5e31350 Compare August 3, 2026 16:43
@Priyanshu-byte-coder

Copy link
Copy Markdown
Owner

Good PR — the stale-while-revalidate approach is right: instant hydration from localCache, fresh snapshot persisted after each fetch, and falling back to the cached snapshot instead of showing an error when the network fails. CI is green and src/lib/localCache.ts is a clean, reusable helper. (Note #2883 attempted the same thing and is now closed, so this is the one I want.)

One thing to fix before I merge — two inline comments are in Hindi:

// SWR fallback: agar live fetch fail ho, cached snapshot dikhta rahe   (GoalTracker.tsx)
// SWR fallback: agar live fetch fail ho, cached snapshot dikhado       (StreakTracker.tsx)

Code comments in this repo are English-only so every contributor can read them. Please reword those two (e.g. // SWR fallback: if the live fetch fails, keep showing the cached snapshot) and I'll merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc26 GSSoC 2026 contribution type:bug GSSoC type bonus: bug fix type:design GSSoC type bonus: UI/design (+10 pts) type:feature GSSoC type bonus: new feature type:performance GSSoC type bonus: performance (+15 pts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] Add Stale-While-Revalidate (SWR) Local Storage Cache Layer for Offline Dashboard Resiliency

2 participants